package com.mrt.chatgpt.data.types.sdk.weixin;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.io.Writer;
import java.util.*;
/**
 * @Author 86135
 * @Date 2024/3/15 20:00
 * @Description
 * @Version 1.0
 * @快捷键 getterANDsetter ALT+Insert
 * @快捷键 Ctrl+/或者Ctrl+Shift+/都可以快速注释
 * @快捷键 Ctrl+D 快速复制代码
 * @“ctrl+r”快捷键,用于当前文件内容替换,指的是在当前打开的文件中替换匹配的字符,只操作一个文件;
 * @ALT+鼠标左键 整列编辑
 * @快捷键提示 ALT+Enter
 * @快捷键 快速写注释：在方法函数上方输入/** 然后回车
 * @快捷键 Ctrl+O，选择重写的方法
 * @快捷键 ALT+INSERT
 */
public class XmlUtil {
    /**
     * 解析微信发来的请求(xml)
     */
    public static Map<String, String> xmlToMap(HttpServletRequest   request) throws Exception {
                //从request中取得输入流
        try(InputStream inputStream = request.getInputStream()){
            //将解析的结果储存在HashMap中
            Map<String,String> map = new HashMap<>();
            //获取输入流
            SAXReader reader = new SAXReader();
            //得到xml文档
            Document document = reader.read(inputStream);
            //得到xml根元素
            Element root = document.getRootElement();
            //获取根元素的所有子节点
            List<Element> elementList = root.elements();
            //遍历所有子节点
            for(Element e : elementList)
                map.put(e.getName(), e.getText());
            //释放资源
            inputStream.close();
            return map;
        }
    }

    /**
     * 将map转化成xml响应给微信服务器
     */
    static String mapToXML(Map map){
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        mapToXML2(map, sb);
        sb.append("</xml>");
        try{
            return sb.toString();
        }catch (Exception e){
            return null;
        }
    }

    private static void mapToXML2(Map map, StringBuffer sb) {
        Set set = map.keySet();
        for(Object o : set){
            String key = (String) o;
            Object value = map.get(key);
            if(null == value)
                value = "";
            if(value.getClass().getName().equals("java.util.ArrayList")){
                ArrayList list = (ArrayList) map.get(key);
                sb.append("<").append(key).append(">");
                for(Object o1 : list){
                    HashMap hm = (HashMap) o1;
                    mapToXML2(hm, sb);
                }
                sb.append("</").append(key).append(">");
            }else{
                if(value instanceof  HashMap){
                    sb.append("<").append(key).append(">");
                    mapToXML2((HashMap)value,sb);
                    sb.append("</").append(key).append(">");
                }else {
                    sb.append("<").append(key).append("><![CDATA[").append(value).append(")]<>/").append(key).append(">");
                }
            }
        }
    }

    /**
     * xml转成bean泛型方法
     */
    public static <T> T xmlToBean(String resultXml, Class clazz){
        // XStream对象设置默认安全防护，同时设置允许的类
        XStream xStream = new XStream(new DomDriver());
        XStream.setupDefaultSecurity(xStream);
        xStream.allowTypes(new Class[]{clazz});
        xStream.processAnnotations(new Class[]{clazz});
        xStream.setMode(XStream.ID_REFERENCES);
        xStream.alias("xml",clazz);
        return (T) xStream.fromXML(resultXml);
    }


    /**
     * bean转成微信的xml消息格式
     */
public static String beanToXml(Object object){
    XStream xStream = getMyXStream();
    xStream.alias("xml",object.getClass());
    xStream.processAnnotations(object.getClass());
    String xml = xStream.toXML(object);
    if(!StringUtils.isEmpty(xml)){
        return xml;
    }else {
        return null;
    }
}

    public static XStream getMyXStream() {
        return new XStream(new XppDriver() {
            @Override
            public HierarchicalStreamWriter createWriter(Writer out) {
                return new PrettyPrintWriter(out) {
                    // 对所有xml节点都增加CDATA标记
                    boolean cdata = true;

                    @Override
                    public void startNode(String name, Class clazz) {
                        super.startNode(name, clazz);
                    }

                    @Override
                    protected void writeText(QuickWriter writer, String text) {
                        if (cdata && !StringUtils.isNumeric(text)) {
                            writer.write("<![CDATA[");
                            writer.write(text);
                            writer.write("]]>");
                        } else {
                            writer.write(text);
                        }
                    }
                };
            }
        });
    }

}
